from asyncio.log import logger
import os ,random, logging
import subprocess
logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)

# adb_path=os.path.join('adb','adb.exe')
adb_path = 'adb'

class Adb():
    '''
        用来创建一个设备连接
    '''
    def __init__(self,device=None,ipAddress=None,port=None) -> None:
        '''
            初始化使用IP地址和端口
            ipAddress: 设备IP，本地为127.0.0.1
            port: 开放端口 默认为5555
            初始化使用设备id
            device: 设备id

            例：
            使用设备IP Adb(ipAddress = '192.168.123.186',port = 43137)
            使用设备id Adb(device = 'd5c42b2a')

        '''
        logging.debug('连接设备')
        if ipAddress is not None:
            self.connect = ipAddress+':'+str(port)   # 连接设备字符串
            com = adb_path+' connect '+self.connect
            logging.debug(com)
            output = subprocess.Popen(com,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,shell=True).stdout.read().decode('utf-8')
            logging.debug(output)
            self.connect = ' -s '+self.connect
            if output.split(' ')[0] == 'connected' or output.split(' ')[0] == 'already' :
                logging.info('连接成功')
                self.resolution = self.getScreenResolution()
            else:
                logging.error('无法连接设备')
                logging.error(output)
                raise Exception('无法连接设备\n'+str(output))
        elif device is not None:
            self.connect = device
            output = subprocess.Popen(adb_path+' devices',stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read().decode('utf-8')
            self.connect = ' -s '+self.connect
            b = [i.split('\t') for i in output.splitlines()[1:-1]]
            for a in b:
                if a[0]==device and a[1]=='device':
                    logging.info('连接成功')
                    self.resolution = self.getScreenResolution()
                    break
            else:
                logging.error('无法连接设备')
                logging.error(output)
                raise Exception('无法连接设备\n'+str(output))
        else:
            msg='参数不能为空'
            logging.error(msg)
            raise ValueError(msg)

        

    def tap(self,x:float,y:float,duration:int=0,random_r:float=0)->int:
        '''
            点击屏幕
            x,y为点击的屏幕坐标
            duration: 点击时长(ms)
            random_r: 随机点击半径
            Return 命令执行状态

        '''
        assert x < self.resolution[0]
        assert y < self.resolution[1]
        x+=round(random.randint(-random_r,random_r),1)
        y+=round(random.randint(-random_r,random_r),1)
        logging.info('TAP: {0},{1},{2}'.format(x,y,duration))
        
        if duration != 0:
            self.swap(x,y,x,y,duration)
        com = adb_path+self.connect+' shell input tap '+str(x)+' '+str(y)
        logging.debug(com)
        return os.system(com)
    
    def swap(self,x1:float,y1:float,x2:float,y2:float,duration:int = 0,random_r:float=0)->int:
        '''
            滑动点击
            x1,y1: 起始点坐标
            x2,y2: 终点坐标
            duration: 点击时长(ms)
            random_r: 随机点击半径
            Return: 命令执行状态
        '''
        assert x1 < self.resolution[0]
        assert x1 < self.resolution[1]
        x1+=round(random.randint(-random_r,random_r),1)
        y1+=round(random.randint(-random_r,random_r),1)
        x2+=round(random.randint(-random_r,random_r),1)
        y2+=round(random.randint(-random_r,random_r),1)
        logging.info('SWIPE: {0},{1}->{2},{3} {4}'.format(x1,y1,x2,y2,duration))
        com = adb_path+self.connect+' shell input swipe '+str(x1)+' '+str(y1)+' ' + str(x2)+' ' + str(y2)+' '+ str(duration)
        logging.debug(com)
        return os.system(com)

    def screenCap(self):
        '''
            屏幕截图存储至/sdcard/01.png
            Return 窗口分辨率
        '''
        output = subprocess.Popen(adb_path+self.connect+' shell screencap -p /sdcard/01.png',stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read().decode('utf-8')
        
        return output.split(' ')[-1].split('x')
    
    def pullBackScreenCap(self,savePath=None,delete=True):
        '''
            将截图的屏幕传回到savePath，如e://savepath//01.png
            默认传回./adb/screen.png
        '''
        if savePath is None:
            # 默认
            os.system(adb_path+self.connect+' pull /sdcard/01.png '+os.path.join('adb','screen.png'))
            
        else:
            os.system(adb_path+self.connect+' pull /sdcard/01.png '+savePath)
        
        if delete is True:
            self.rmFile(filePath='/sdcard/01.png')
    
    def getScreenResolution(self)->tuple[int,int]:
        '''
            获得屏幕分辨率
            Return (tuple) 屏幕分辨率
        '''
        logging.debug('获取屏幕分辨率')
        com = adb_path+self.connect+' shell wm size'
        logging.debug(com)
        result = os.popen(adb_path+self.connect+' shell wm size').read().strip()
        result = str(result).split('\n')
        logging.info(result)
        result = result[-1].split(' ')[2].split('x')
        result = (int(result[0]),int(result[1]))
        assert result[0] is not int and result[1] is not int 
        logging.info('分辨率'+str(result))
        return result
    
    def rmFile(self,filePath):
        '''
            删除手机中文件
            Return 是否成功删除
        '''
        result = os.popen(adb_path+self.connect+' shell rm '+filePath).read()
        return result
    


if __name__ == '__main__':
    adb = Adb(ipAddress='192.168.1.52',port=38961)
    adb.tap(1079,2399)